package cn.com.company.common.http.util;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.*;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Title: HttpClientUtil<br>
 * Description: HttpClientUtil<br>
 * Company: xxx<br>
 * CreateDate:2020年12月28日 上午8:29:56
 * 
 */
public class HttpClientUtil {
  private static Logger logger = Logger.getLogger(HttpClientUtil.class);

  public static String doPost(String url, Map<String, Object> params) throws Exception {
    return doPostBase(url, null, "UTF-8", params, 30 * 1000);
  }

  public static String doPost(String url, Map<String, Object> params, int timeOutTime)
      throws Exception {
    return doPostBase(url, null, "UTF-8", params, timeOutTime);
  }

  public static String doPostBase(String url, String contentType, String contentCharset,
      Map<String, Object> params, int timeOutTime)
      throws Exception {
    logger.info("javabase的httpClient post请求------>start,url=" + url + ",params=" + params);

    String result = null;

    // 创建提交方法实例
    PostMethod method = null;

    try {
      // 创建一个HTTP客户端(HttpClient)的实例
      HttpClient httpClient = new HttpClient();

      method = new PostMethod(url);

      // 读取超时，30秒不回我就抛异常了。
      httpClient.getHttpConnectionManager().getParams().setSoTimeout(timeOutTime);

      // 设置代理服务器地址和端口
      // client.getHostConfiguration().setProxy("proxy_host_addr",proxy_port);

      // 设置编码
      httpClient.getParams().setContentCharset(contentCharset);

      if (StringUtils.isEmpty(contentType)) {
        // 如果contentType为空则默认使用form表单提交的形式
        method.setRequestHeader(HTTP.CONTENT_TYPE,
            "application/x-www-form-urlencoded;charset=" + contentCharset);
      } else {
        method.setRequestHeader(HTTP.CONTENT_TYPE, contentType);
      }

      List<NameValuePair> list = new ArrayList<NameValuePair>();

      for (String temp : params.keySet()) {
        list.add(new NameValuePair(temp, params.get(temp).toString()));
      }

      method.setRequestBody(list.toArray(new NameValuePair[params.size()]));

      // 执行请求
      httpClient.executeMethod(method);
      // 打印返回的信息
      logger.info("javabase的httpClient post请求------>returnStatus=" + method.getStatusLine());
      result = method.getResponseBodyAsString();
    } finally {
      // 释放连接
      if (method != null) {
        method.releaseConnection();
      }

    }

    logger.info("javabase的httpClient post请求------>end,result=" + result);
    return result;
  }

  public static byte[] doGetReturnByte(String url) throws Exception {
    logger.info("javabase的httpClient get请求------>start,url=" + url);
    byte[] result = null;
    GetMethod method = null;

    try {
      method = new GetMethod(url);
      HttpClient httpClient = new HttpClient();
      // client.getParams().setContentCharset("UTF-8");
      method.setRequestHeader("ContentType", "application/x-www-form-urlencoded");
      method.setRequestHeader("Accept-Charset", "utf-8");
      // 读取超时，10秒不回我就抛异常了。
      httpClient.getHttpConnectionManager().getParams().setSoTimeout(10 * 1000);
      httpClient.executeMethod(method);
      logger.info(
          "javabase的httpClient doGetReturnByte请求------>returnStatus=" + method.getStatusLine());
      InputStream input = method.getResponseBodyAsStream();
      result = input2byte(input);
    } finally {
      // 释放连接
      if (method != null) {
        method.releaseConnection();
      }
    }
    logger.info("javabase的httpClient get请求------>end,result=" + result);

    return result;
  }

  public static String doGetReturnString(String url) throws Exception {
    logger.info("javabase的httpClient get请求------>start,url=" + url);
    GetMethod method = null;
    String result;
    try {
      HttpClient httpClient = new HttpClient();
      method = new GetMethod(url);
      // client.getParams().setContentCharset("UTF-8");
      method.setRequestHeader("ContentType", "application/x-www-form-urlencoded");
      method.setRequestHeader("Accept-Charset", "utf-8");
      // 读取超时，10秒不回我就抛异常了。
      httpClient.getHttpConnectionManager().getParams().setSoTimeout(10 * 1000);
      httpClient.executeMethod(method);
      logger.info("javabase的httpClient post请求------>doGetReturnString=" + method.getStatusLine());
      result = method.getResponseBodyAsString();
      logger.info("javabase的httpClient get请求------>end,result=" + result);
    } finally {
      if (method != null) {
        // 释放连接
        method.releaseConnection();
      }
    }
    return result;
  }

  /**
   * Title: doPostByJson<br>
   * Description: doPostByJson<br>
   * CreateDate: 2020年12月28日 上午8:35:36<br>
   * 
   * @category doPostByJson
   * @param url
   * @param paramJsonStr
   * @param headerMap
   * @return
   * @throws Exception
   */
  public static String doPostByJson(String url, String paramJsonStr,
      Map<String, String> headerMap, int timeOutTime) throws Exception {
    logger.info("javabase的httpClient postByJson请求------>start,url=" + url + ",paramJsonStr="
        + paramJsonStr + ",headerMap=" + headerMap);

    String resultStr;
    PostMethod method = null;
    try {
      HttpClient httpClient = new HttpClient();
      method = new PostMethod(url);

      if (headerMap != null) {
        for (String key : headerMap.keySet()) {
          method.setRequestHeader(key, headerMap.get(key));
        }
      }
      method.setRequestHeader(HTTP.CONTENT_TYPE, "application/json;charset=UTF-8");
      method.setRequestBody(paramJsonStr);
      /**
       * modify by xxx 2020年8月25日16:08:45 改成30秒 classin返回太慢了
       */
      // 读取超时，30秒不回我就抛异常了。
      httpClient.getHttpConnectionManager().getParams().setSoTimeout(timeOutTime);

      int status = httpClient.executeMethod(method);
      logger
          .info("javabase的httpClient doPostByJson请求------>returnStatus=" + method.getStatusLine());
      logger.info("status=========================" + status);
      resultStr = method.getResponseBodyAsString();
    } finally {
      if (method != null) {
        // 释放连接
        method.releaseConnection();
      }
    }

    logger.info("javabase的httpClient postByJson请求------>end,result=" + resultStr);
    return resultStr;
  }

  /**
   * Title: doPostByJson<br>
   * Description: 不传默认30秒<br>
   * CreateDate: 2020年12月28日 上午8:35:36<br>
   * 
   * @category doPostByJson
   * @param url
   * @param paramJsonStr
   * @param headerMap
   * @return
   * @throws Exception
   */
  public static String doPostByJson(String url, String paramJsonStr,
      Map<String, String> headerMap) throws Exception {
    return doPostByJson(url, paramJsonStr, headerMap, 30 * 1000);
  }

  /**
   * Title: doPostByJson<br>
   * Description: doPostByJson<br>
   * CreateDate: 2020年12月28日 上午8:35:36<br>
   * 
   * @category doPostByJson
   * @param url
   * @param paramXmlStr
   * @param headerMap
   * @return
   * @throws Exception
   */
  public static String doPostByXml(String url, String paramXmlStr, Map<String, String> headerMap)
      throws Exception {
    logger.info("javabase的httpClient doPostByXml请求------>start,url=" + url + ",paramXmlStr="
        + paramXmlStr + ",headerMap=" + headerMap);

    PostMethod method = null;
    String resultStr;
    InputStream inputStream = null;
    BufferedReader br = null;
    try {
      HttpClient httpClient = new HttpClient();
      method = new PostMethod(url);

      if (headerMap != null) {
        for (String key : headerMap.keySet()) {
          method.setRequestHeader(key, headerMap.get(key));
        }
      }
      method.setRequestHeader(HTTP.CONTENT_TYPE, "application/xml;charset=UTF-8");
      method.setRequestBody(paramXmlStr);
      // 读取超时，10秒不回我就抛异常了。
      httpClient.getHttpConnectionManager().getParams().setSoTimeout(10 * 1000);

      int status = httpClient.executeMethod(method);
      logger.info("status=========================" + status);

      inputStream = method.getResponseBodyAsStream();
      br = new BufferedReader(new InputStreamReader(inputStream));
      StringBuffer stringBuffer = new StringBuffer();
      String str = "";
      while ((str = br.readLine()) != null) {
        stringBuffer.append(str);
      }
      resultStr = stringBuffer.toString();
      logger.info("javabase的httpClient doPostByXml请求------>end,result=" + resultStr);
    } finally {
      if (inputStream != null) {
        inputStream.close();
      }
      if (br != null) {
        br.close();
      }
      if (method != null) {
        // 释放连接
        method.releaseConnection();
      }
    }
    return resultStr;
  }

  /**
   * 
   * Title: get请求能设置头部信息<br>
   * Description: doGet<br>
   * CreateDate: 2020年8月25日 上午11:04:26<br>
   * 
   * @category get请求能设置头部信息
   * @param url
   * @param headerMap
   *          请求头信息
   */
  public static String doGet(String url, Map<String, String> headerMap) throws Exception {
    logger.info("javabase的httpClient get请求------>start,url=" + url + ",headerMap=" + headerMap);

    String resultStr;
    GetMethod method = null;
    try {
      HttpClient httpClient = new HttpClient();
      method = new GetMethod(url);

      if (headerMap != null) {
        for (String key : headerMap.keySet()) {
          method.setRequestHeader(key, headerMap.get(key));
        }
      }
      // 读取超时，10秒不回我就抛异常了。
      httpClient.getHttpConnectionManager().getParams().setSoTimeout(60 * 1000);

      int status = httpClient.executeMethod(method);
      logger
          .info("javabase的httpClient get请求------>returnStatus=" + method.getStatusLine());
      logger.info("status=========================" + status);
      resultStr = method.getResponseBodyAsString();
    } finally {
      if (method != null) {
        // 释放连接
        method.releaseConnection();
      }
    }

    logger.info("javabase的httpClient get请求------>end,result=" + resultStr);
    return resultStr;
  }

  /**
   * 
   * Title: doDelete请求能设置头部信息<br>
   * Description: doDelete<br>
   * CreateDate: 2020年8月25日 上午11:14:03<br>
   * 
   * @category doDelete请求能设置头部信息
   * @param url
   * @param headerMap
   *          请求头信息
   */
  public static String doDelete(String url, Map<String, String> headerMap) throws Exception {
    logger.info("javabase的httpClient doDelete请求------>start,url=" + url + ",headerMap="
        + headerMap);

    String resultStr;
    DeleteMethod method = null;
    try {
      HttpClient httpClient = new HttpClient();
      method = new DeleteMethod(url);

      if (headerMap != null) {
        for (String key : headerMap.keySet()) {
          method.setRequestHeader(key, headerMap.get(key));
        }
      }
      // 读取超时，10秒不回我就抛异常了。
      httpClient.getHttpConnectionManager().getParams().setSoTimeout(30 * 1000);

      int status = httpClient.executeMethod(method);
      logger.info("javabase的httpClient doDelete请求------>returnStatus=" + method.getStatusLine());
      logger.info("status=========================" + status);
      resultStr = method.getResponseBodyAsString();
    } finally {
      if (method != null) {
        // 释放连接
        method.releaseConnection();
      }
    }

    logger.info("javabase的httpClient doDelete请求------>end,result=" + resultStr);
    return resultStr;
  }

  private static final byte[] input2byte(InputStream inStream)
      throws IOException {
    ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
    byte[] buff = new byte[100];
    int rc = 0;
    while ((rc = inStream.read(buff, 0, 100)) > 0) {
      swapStream.write(buff, 0, rc);
    }
    byte[] in2b = swapStream.toByteArray();
    return in2b;
  }

  /**
   * Title: doPostByJson<br>
   * Description: 这里可以和post放成一个方法，单处于安全考虑，还是有写了一个<br>
   * CreateDate: 2020年12月28日 上午8:35:36<br>
   * 
   * @category doPostByJson
   * @param url
   * @param paramJsonStr
   * @param headerMap
   * @return
   * @throws Exception
   */
  public static String doPutByJson(String url, String paramJsonStr,
      Map<String, String> headerMap) throws Exception {
    logger.info("javabase的httpClient postByJson请求------>start,url=" + url + ",paramJsonStr="
        + paramJsonStr + ",headerMap=" + headerMap);

    String resultStr;
    PutMethod method = null;
    try {
      HttpClient httpClient = new HttpClient();
      method = new PutMethod(url);

      if (headerMap != null) {
        for (String key : headerMap.keySet()) {
          method.setRequestHeader(key, headerMap.get(key));
        }
      }
      method.setRequestHeader(HTTP.CONTENT_TYPE, "application/json;charset=UTF-8");
      method.setRequestBody(paramJsonStr);
      /**
       * modify by xxx 2020年8月25日16:08:45 改成30秒 classin返回太慢了
       */
      // 读取超时，30秒不回我就抛异常了。
      httpClient.getHttpConnectionManager().getParams().setSoTimeout(30 * 1000);

      int status = httpClient.executeMethod(method);
      logger
          .info("javabase的httpClient doPutByJson请求------>returnStatus=" + method.getStatusLine());
      logger.info("status=========================" + status);
      resultStr = method.getResponseBodyAsString();
    } finally {
      if (method != null) {
        // 释放连接
        method.releaseConnection();
      }
    }

    logger.info("javabase的httpClient doPutByJson请求------>end,result=" + resultStr);
    return resultStr;
  }

  /**
   * Title: doPostByJson<br>
   * Description: doPostByJson<br>
   * CreateDate: 2020年12月28日 上午8:35:36<br>
   * 
   * @category doPostByJson
   * @param url
   * @param paramJsonStr
   * @param headerMap
   * @return
   * @throws Exception
   */
  public static String doDeleteByJson(String url, String paramJsonStr,
      Map<String, String> headerMap) throws Exception {
    logger.info("javabase的httpClient deleteByJson请求------>start,url=" + url + ",paramJsonStr="
        + paramJsonStr + ",headerMap=" + headerMap);

    String resultStr;
    HttpDeleteMethodJson method = null;
    try {
      HttpClient httpClient = new HttpClient();
      method = new HttpDeleteMethodJson(url);

      if (headerMap != null) {
        for (String key : headerMap.keySet()) {
          method.setRequestHeader(key, headerMap.get(key));
        }
      }
      method.setRequestHeader(HTTP.CONTENT_TYPE, "application/json;charset=UTF-8");
      method.setRequestBody(paramJsonStr);

      /**
       * modify by xxx 2020年8月25日16:08:45 改成30秒 classin返回太慢了
       */
      // 读取超时，30秒不回我就抛异常了。
      httpClient.getHttpConnectionManager().getParams().setSoTimeout(30 * 1000);

      int status = httpClient.executeMethod(method);
      logger
          .info("javabase的httpClient deleteByJson请求------>returnStatus=" + method.getStatusLine());
      logger.info("status=========================" + status);
      resultStr = method.getResponseBodyAsString();
    } finally {
      if (method != null) {
        // 释放连接
        method.releaseConnection();
      }
    }

    logger.info("javabase的httpClient deleteByJson请求------>end,result=" + resultStr);
    return resultStr;
  }

  /**
   * 
   * Title: HttpClient中转文件<br>
   * Description: HttpClient中转文件<br>
   * CreateDate: 2020年7月17日 下午2:49:37<br>
   * 
   * @category HttpClient中转文件
   * @param multipartFileList
   * @return
   */
  public static String doPostByMultipartFile(String url, List<MultipartFile> multipartFileList) {
    CloseableHttpClient httpClient = HttpClients.createDefault();
    String result = "";
    try {
      HttpPost httpPost = new HttpPost(url);
      MultipartEntityBuilder builder = MultipartEntityBuilder.create();
      for (MultipartFile multipartFile : multipartFileList) {
        // 文件流
        builder.addBinaryBody("multipartFileList", multipartFile.getInputStream(),
            ContentType.MULTIPART_FORM_DATA,
            multipartFile.getOriginalFilename());
        // 类似浏览器表单提交，对应input的name和value
        builder.addTextBody("filename", multipartFile.getOriginalFilename());
      }
      HttpEntity entity = builder.build();
      httpPost.setEntity(entity);
      // 执行提交
      HttpResponse response = httpClient.execute(httpPost);
      HttpEntity responseEntity = response.getEntity();
      if (responseEntity != null) {
        // 将响应内容转换为字符串
        result = EntityUtils.toString(responseEntity, Charset.forName("UTF-8"));
      }
    } catch (IOException e) {
      e.printStackTrace();
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      try {
        httpClient.close();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
    return result;
  }
}

/**
 * 
 * Title: 由于httpclient自带的delete方法没法传参数所以这里仿照put的写法自己写一个httpdelete<br>
 * Description: HttpDeleteMethodJson<br>
 * Company: xxx<br>
 * CreateDate:2020年1月31日 下午3:55:09
 * 
 */
class HttpDeleteMethodJson extends EntityEnclosingMethod {
  public HttpDeleteMethodJson() {}

  public HttpDeleteMethodJson(String uri) {
    super(uri);
  }

  @Override
  public String getName() {
    return "DELETE";
  }
}
